 package com.gss.armory.util;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.PostConstruct;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.gss.armory.domain.BusinessUnitDetailsDTO;
import com.gss.armory.domain.BusinessUnitTypeDTO;
import com.gss.armory.domain.CompanyDetailsDTO;
import com.gss.armory.domain.DepartmentDetailsDTO;
import com.gss.armory.domain.DocGeneralDetailsDTO;
import com.gss.armory.domain.DocReviewerApproverForWFDTO;
import com.gss.armory.domain.DocumentCategoryDTO;
import com.gss.armory.domain.DocumentSubCategory;
import com.gss.armory.domain.DocumentTypeDTO;
import com.gss.armory.domain.LocationDetailsDTO;
import com.gss.armory.domain.MasterDetailsForDMSWFDTO;
import com.gss.armory.domain.UserActivityGroup;
import com.gss.armory.domain.UserActivityGroup.DocActivityType;
import com.gss.armory.persistence.CommonDAO;
import com.gss.armory.persistence.ReportsDAO;
import com.gss.common.util.ApplicationConstants;
import com.gss.common.util.ApplicationMaps;
import com.gss.security.domain.LocationMasterDTO;
import com.gss.security.domain.RoleDetailsDTO;
import com.gss.security.domain.SuperficialRolesMapping;
import com.gss.security.domain.UserDetailsDTO;
import com.gss.security.persistence.AuthenticationDAO;
import com.gss.security.service.AuthenticationService;

@Component
public class BootUpLoader {
	
	@Autowired
	private CommonDAO commonDAO;
	
	@Autowired
	private ReportsDAO reportsDAO;
	
	@Autowired
	private AuthenticationService authenticationService;
	
	@Autowired
	private AuthenticationDAO authenticationDAO;
	
	private Logger logger = Logger.getLogger(BootUpLoader.class);
	
	@PostConstruct
	public void bootUp()
	{
		logger.debug("Booting... :: Inside BootupLoader...");
		
		loadUserMap();
		loadUserGroupMap();
		loadRoleName();
		loadCompany();
		loadBusLocs();
		loadLocationMaster();
		loadDocTypeMap();
		loadArmoryMasterData();
		loadSuperficialRoleMappingData();
		//loadDepts();
		loadStaticMaps();
		loadDocumentDetail();
		
		InputStream fis = null;
		try {
			logger.debug(System.getProperty("templateFilePath")+" --- default property");
			//fis = new FileInputStream(new File(this.getClass().getResource("/watermarktemplate.pdf").toURI()));
			fis = this.getClass().getResourceAsStream("/watermarktemplate.pdf");
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			byte[] bytesRead = new byte[1024];
			int counter = fis.read(bytesRead);
			while(counter > 0){
				baos.write(bytesRead, 0, counter);
				counter = fis.read(bytesRead);
			}
			baos.flush();
			ApplicationConstants.WATERMARK_TEMPLATE_BYTES = baos.toByteArray();
			baos.close();
			baos = null;
			fis.close();
			fis = null;
			logger.debug("template loaded successfully, size - " + ApplicationConstants.WATERMARK_TEMPLATE_BYTES.length);
		} catch (Exception e) {
			//e.printStackTrace();
			logger.error(e.getMessage(),e);
		}
		
	}
	


	private void loadStaticMaps() {

		ApplicationMaps.SearchViewMap.put(ApplicationConstants.VIEW_OP, "docDetailsView");
		ApplicationMaps.SearchViewMap.put(ApplicationConstants.RENEW_OP, "docDetailsRenew");
		ApplicationMaps.SearchViewMap.put(ApplicationConstants.VERSION_OP, "docDetailsVersion");
		ApplicationMaps.SearchViewMap.put(ApplicationConstants.LINK_OP, "docDetailsLink");
		ApplicationMaps.SearchViewMap.put(ApplicationConstants.DEACT_OP, "docDetailsDeact");
		
	}

	public void loadUserMap(){
		List<UserDetailsDTO> userList = authenticationDAO.loadAll(UserDetailsDTO.class);
		if(null != userList && userList.size() > 0){
			logger.debug("Number of rows in user details table: " + userList.size());
			for(UserDetailsDTO userDetails : userList){
				ApplicationMaps.USERID_USERNAME_MAP.put(userDetails.getUsername(),userDetails.getUserDisplayName());
				ApplicationMaps.USERID_EMAIL_MAP.put(userDetails.getUsername(), userDetails.getEmailId());
				ApplicationMaps.USERID_USER_MAP.put(userDetails.getUsername(), userDetails);
			}
			logger.debug("Number of registered users in system: " + ApplicationMaps.USERID_USERNAME_MAP.size());
		}
	}
	
	public void loadUserGroupMap()
	{
		//load all the users and respective groups in ApplicationMaps.USER_ACTIVITY_GROUP_MAP
		
		List<UserActivityGroup> activityGroups = new ArrayList<UserActivityGroup>();
		activityGroups = commonDAO.loadAll(UserActivityGroup.class);
		UserActivityGroup.DocActivityType activityType = UserActivityGroup.DocActivityType.View; 
		for (UserActivityGroup userActivityGroup : activityGroups) {
			if(ApplicationMaps.USER_ACTIVITY_GROUP_MAP.containsKey(userActivityGroup.getUsername()))
			{
				List<Long> grpIds = ApplicationMaps.USER_ACTIVITY_GROUP_MAP.get(userActivityGroup.getUsername());
			}
			else
			{
				List<Long> list = new ArrayList<Long>();
				ApplicationMaps.USER_ACTIVITY_GROUP_MAP.put(userActivityGroup.getUsername(), list);
			}
			//view permissions
			if(userActivityGroup.getActivityType().equals(DocActivityType.View))
			{
				if(ApplicationMaps.USER_VIEW_GROUP_MAP.containsKey(userActivityGroup.getUsername()))
				{
					List<Long> grpIds = ApplicationMaps.USER_VIEW_GROUP_MAP.get(userActivityGroup.getUsername());
				}
				else
				{
					List<Long> list = new ArrayList<Long>();
					ApplicationMaps.USER_VIEW_GROUP_MAP.put(userActivityGroup.getUsername(), list);
				}
			}
			else if(userActivityGroup.getActivityType().equals(DocActivityType.Print))
			{
				if(ApplicationMaps.USER_PRINT_GROUP_MAP.containsKey(userActivityGroup.getUsername()))
				{
					List<Long> grpIds = ApplicationMaps.USER_ACTIVITY_GROUP_MAP.get(userActivityGroup.getUsername());
				}
				else
				{
					List<Long> list = new ArrayList<Long>();
					ApplicationMaps.USER_PRINT_GROUP_MAP.put(userActivityGroup.getUsername(), list);
				}
			}
		}
	}
	
	public void loadDocTypeMap()
	{
		List<DocumentTypeDTO> documentTypeDTOs = commonDAO.loadAll(DocumentTypeDTO.class);
		
		if(null == documentTypeDTOs || documentTypeDTOs.size() == 0)
			return;
		
		if(null != documentTypeDTOs && ApplicationConstants.ALL_INT != documentTypeDTOs.size()){
			logger.debug("Number of rows in document type table are: " + documentTypeDTOs.size());
			
			List<DocumentCategoryDTO> categoryDTOs = new ArrayList<DocumentCategoryDTO>();
			List<DocumentSubCategory> documentSubCategories = new ArrayList<DocumentSubCategory>();
			for (DocumentTypeDTO documentTypeDTO : documentTypeDTOs) {
				ApplicationMaps.DOCUMENT_TYPE_ID_NAME_MAP.put(documentTypeDTO.getDtId(), documentTypeDTO.getDtName());
				ApplicationMaps.DOCUMENT_TYPE_ID_MAP.put(documentTypeDTO.getDtId(), documentTypeDTO);
				categoryDTOs = documentTypeDTO.getDtCategoryList();
				if(categoryDTOs!=null && categoryDTOs.size() > 0)
				{
					ApplicationMaps.DOC_TYP_DOC_CAT_MAP.put(documentTypeDTO.getDtId(),categoryDTOs);
					
					for (DocumentCategoryDTO documentCategoryDTO : categoryDTOs) {
						ApplicationMaps.DOCUMENT_CAT_ID_MAP.put(documentCategoryDTO.getDcId(),documentCategoryDTO.getDcName());
						documentSubCategories = documentCategoryDTO.getDcSubCatList();
						if(documentSubCategories!=null && documentSubCategories.size() > 0)
						{
							ApplicationMaps.DOC_CAT_DOC_SUBCAT_MAP.put(documentCategoryDTO.getDcId(), documentSubCategories);
							for (DocumentSubCategory documentSubCategory : documentSubCategories) {
								ApplicationMaps.DOCUMENT_SUB_CAT_ID_MAP.put(documentSubCategory.getDscId(), documentSubCategory.getDscName());
							}
						}
					}
				}
			}
			logger.debug("Number of registered document types in the system are: " + ApplicationMaps.DOCUMENT_TYPE_ID_NAME_MAP.size());
		}
		
	}
	
	public void loadLocationMaster() {
		List<LocationMasterDTO> locationMasterList = new ArrayList<LocationMasterDTO>();
		locationMasterList = commonDAO.loadAll(LocationMasterDTO.class);
		if(null != locationMasterList && locationMasterList.size() > 0){
			logger.debug("Number of rows in location master table: " + locationMasterList.size());
			
			for(LocationMasterDTO locationMasterDTO : locationMasterList){
				ApplicationMaps.LOCATION_DETAILS_MAP.put(locationMasterDTO.getLocId(), locationMasterDTO);
				
				if(!ApplicationMaps.STATE_DISTRICT_MAP.containsKey(locationMasterDTO.getState())){
					List<String> districtList = new ArrayList<String>();
					districtList.add(locationMasterDTO.getDistrict());
					ApplicationMaps.STATE_DISTRICT_MAP.put(locationMasterDTO.getState(), districtList);
				}
				else{
					ApplicationMaps.STATE_DISTRICT_MAP.get(locationMasterDTO.getState()).add(locationMasterDTO.getDistrict());
				}
				
				if(!ApplicationMaps.DISTRICT_CITY_MAP.containsKey(locationMasterDTO.getDistrict())){
					List<String> cityList = new ArrayList<String>();
					cityList.add(locationMasterDTO.getCity());
					ApplicationMaps.DISTRICT_CITY_MAP.put(locationMasterDTO.getDistrict(), cityList);
				}
				else{
					ApplicationMaps.DISTRICT_CITY_MAP.get(locationMasterDTO.getDistrict()).add(locationMasterDTO.getCity());
				}
			}
			logger.debug("Number of registered locations as location master in the system are: " + ApplicationMaps.LOCATION_DETAILS_MAP.size());
		}
		
	}
	
	public void loadCompany() {
		List<CompanyDetailsDTO> companyDetailsDTOs = null;
		try {
			companyDetailsDTOs = commonDAO.loadAllCompany();
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
		if(null!= companyDetailsDTOs && companyDetailsDTOs.size() > 0){
			for(CompanyDetailsDTO obj : companyDetailsDTOs){
				ApplicationMaps.COMPANYID_COMPANY_MAP.put(obj.getCdId(), obj);
				ApplicationMaps.COMPANY_NAME_COMPANY_CODE_MAP.put(obj.getCdName(), obj.getCdCode());
			}
			logger.debug("Number of registered companies in the system are: " + ApplicationMaps.COMPANYID_COMPANY_MAP.size());
		}

	}
	
	public void loadBusLocs()
	{
		List<CompanyDetailsDTO> companyList = new ArrayList<CompanyDetailsDTO>();
		companyList = commonDAO.loadAll(CompanyDetailsDTO.class);
		if(null != companyList && companyList.size() > 0){
			for(CompanyDetailsDTO company : companyList){
				ApplicationMaps.COMPANYID_COMPANY_MAP.put(company.getCdId(), company);
				List<BusinessUnitDetailsDTO> buList = company.getBusinessUnitList();
				List<LocationDetailsDTO> loclist = company.getLocationList();
				if(null != buList && buList.size() > 0){
					for(BusinessUnitDetailsDTO businessUnit : buList){
						ApplicationMaps.BUID_COMPANYID_MAP.put(businessUnit.getBuId(), company.getCdId());
						ApplicationMaps.BUID_BU_MAP.put(businessUnit.getBuId(), businessUnit);
						List<DepartmentDetailsDTO> depttList = businessUnit.getBuDepttList();
					}
				}
				if(null != loclist){
					ApplicationMaps.COMPANY_LOC_MAP.put(company.getCdId(), loclist);
				}
			}
			logger.debug("Number of registered business units in the system are: " + ApplicationMaps.BUID_BU_MAP.size());			
		}
		
		List<BusinessUnitTypeDTO> buTypeList = commonDAO.loadAll(BusinessUnitTypeDTO.class);
		if(null != buTypeList && buTypeList.size() > 0){
			for(BusinessUnitTypeDTO buType : buTypeList){
				ApplicationMaps.BUTYPE_LIST.add(buType.getBuTypeCode());
				ApplicationMaps.BUTYPE_NAME_DESC_MAP.put(buType.getBuTypeCode(), buType.getBuTypeName());
			}
			logger.debug("Number of registered business unit types in the system are: " + ApplicationMaps.BUTYPE_NAME_DESC_MAP.size());
		}
		
		List<DepartmentDetailsDTO> depttList = commonDAO.loadAll(DepartmentDetailsDTO.class);
		if(null != depttList && depttList.size() > 0){
			for(DepartmentDetailsDTO deptt : depttList){
				ApplicationMaps.DEPTID_DEPTSNAME_MAP.put(deptt.getDdId(),deptt.getDdName());
				ApplicationMaps.DEPARTMENTID_DEPARTMENT_MAP.put(deptt.getDdId(), deptt);
			}
			logger.debug("Number of registered departments in the system are: " + ApplicationMaps.DEPTID_DEPTSNAME_MAP.size());
		}
		
		List<LocationDetailsDTO> locationDetailsDTOs = new ArrayList<LocationDetailsDTO>();
		locationDetailsDTOs = commonDAO.loadAll(LocationDetailsDTO.class);
		if(null != locationDetailsDTOs && ApplicationConstants.ALL_INT != locationDetailsDTOs.size()){
			for (LocationDetailsDTO locationDetailsDTO : locationDetailsDTOs) {
				ApplicationMaps.BU_DEPTS_MAP.put(locationDetailsDTO.getLdId(), locationDetailsDTO.getDepartmentDetailsDTOs());
				ApplicationMaps.LOCID_LOCNAME_MAP.put(locationDetailsDTO.getLdId(), locationDetailsDTO.getLdName());
				ApplicationMaps.LOCID_LOC_MAP.put(locationDetailsDTO.getLdId(), locationDetailsDTO);
			}
			logger.debug("Number of registered locations in the system are: " + ApplicationMaps.LOCID_LOCNAME_MAP.size());
		}
	}
	public void  loadDepts()
	{
		List<DepartmentDetailsDTO> departmentDetailsDTOs = new ArrayList<DepartmentDetailsDTO>();
		departmentDetailsDTOs = commonDAO.loadAll(DepartmentDetailsDTO.class);
		if(departmentDetailsDTOs!=null)
		{
			for (DepartmentDetailsDTO departmentDetailsDTO : departmentDetailsDTOs) {
					ApplicationMaps.DEPTID_DEPTSNAME_MAP.put(departmentDetailsDTO.getDdId(), departmentDetailsDTO.getDdName());
					ApplicationMaps.DEPARTMENTID_DEPARTMENT_MAP.put(departmentDetailsDTO.getDdId(), departmentDetailsDTO);
			}
			logger.debug("Number of registered departments in the system are: " + ApplicationMaps.DEPTID_DEPTSNAME_MAP.size());
		}
	}
	public void loadDocumentDetail()
	{
		List<DocGeneralDetailsDTO> detailsDTOs = commonDAO.loadAll(DocGeneralDetailsDTO.class);
		if(detailsDTOs!=null)
		{
			for(DocGeneralDetailsDTO dto:detailsDTOs){
				ApplicationMaps.DOCUMENT_ID_NAME_MAP.put(dto.getDocId(),dto.getDocName());
				if(null != dto.getDocCode() && !"".equals(dto.getDocCode()))
					ApplicationMaps.DOCUMENT_ID_CODE_MAP.put(dto.getDocId(), dto.getDocCode());
			}
			logger.debug("Number of documents in the system: " + ApplicationMaps.DOCUMENT_ID_NAME_MAP.size());
			logger.debug("Number of registered documents in the system: " + ApplicationMaps.DOCUMENT_ID_CODE_MAP.size());
		}
	}
	
	public void loadRoleName() {
		List<RoleDetailsDTO> rolesList = null;
		try {
			rolesList = authenticationService.loadCompleteRoleList();
		} catch (Exception e) {
			logger.error(e.getMessage(),e);
		}
		
		if(null != rolesList && rolesList.size() > 0){
			for(RoleDetailsDTO object : rolesList){
				ApplicationMaps.ROLEID_ROLENAME_MAP.put(object.getRoleId(), object.getRoleDesc());
			}
			logger.debug("Number of registered roles in the system are: " + ApplicationMaps.ROLEID_ROLENAME_MAP.size());
		}
	}
	
	public void loadArmoryMasterData(){
		List<DocReviewerApproverForWFDTO> approverForWFDTOs = commonDAO.loadAll(DocReviewerApproverForWFDTO.class);
		if(null!=approverForWFDTOs && approverForWFDTOs.size()>0){
			for(DocReviewerApproverForWFDTO forWFDTO:approverForWFDTOs){
				ApplicationMaps.ARMORY_REVIEVER_APPROVER.put(forWFDTO.getMasterCode(), forWFDTO);
			}
			logger.debug("Number of registered entries in the master workflow table done so far: " 
					+ ApplicationMaps.ARMORY_REVIEVER_APPROVER.size());
		}
		List<MasterDetailsForDMSWFDTO> detailsForDMSWFDTOs = commonDAO.loadAll(MasterDetailsForDMSWFDTO.class);
		if(null!=detailsForDMSWFDTOs && detailsForDMSWFDTOs.size()>0){
			for(MasterDetailsForDMSWFDTO dmswfdto:detailsForDMSWFDTOs){
				ApplicationMaps.ARMORY_MASTER_DATA.put(dmswfdto.getMasterAttribute(), dmswfdto.isMasterAttributeStatus());
			}
		}
	}

	public void loadSuperficialRoleMappingData(){
		List<SuperficialRolesMapping> superficialRolesMappingsList = commonDAO.loadAll(SuperficialRolesMapping.class);
		if(null != superficialRolesMappingsList && superficialRolesMappingsList.size() > 0){
			for (SuperficialRolesMapping superficialRolesMapping : superficialRolesMappingsList) {
				String userKey = superficialRolesMapping.getUserId() + "#" + superficialRolesMapping.getRoleId();
				String buKey = superficialRolesMapping.getLdId() + "#" + superficialRolesMapping.getRoleId();
				if(ApplicationMaps.SUPERFICIAL_ROLE_MAP_USERID.containsKey(userKey))
					ApplicationMaps.SUPERFICIAL_ROLE_MAP_USERID.get(userKey).add(superficialRolesMapping.getLdId());
				else{
					List<Long> buList = new ArrayList<Long>();
					buList.add(superficialRolesMapping.getLdId());
					ApplicationMaps.SUPERFICIAL_ROLE_MAP_USERID.put(userKey, buList);
				}
				if(ApplicationMaps.SUPERFICIAL_ROLE_MAP_BUID.containsKey(buKey))
					ApplicationMaps.SUPERFICIAL_ROLE_MAP_BUID.get(buKey).add(superficialRolesMapping.getUserId());
				else{
					List<String> usersList = new ArrayList<String>();
					usersList.add(superficialRolesMapping.getUserId());
					ApplicationMaps.SUPERFICIAL_ROLE_MAP_BUID.put(buKey, usersList);
				}
			}
			logger.debug("Number of users having superficial roles in the system are: " + ApplicationMaps.SUPERFICIAL_ROLE_MAP_USERID.size());
		}
	}
}